{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Polynomial Curve Fitting"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data Preparation "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_toy_data(f, sample_size, std=0.25, noise=True):\n",
    "    x = np.linspace(0, 1, sample_size)\n",
    "    if noise:\n",
    "        y = f(x) + np.random.normal(scale=std, size=x.shape)\n",
    "    else:\n",
    "        y = f(x)            \n",
    "    return x, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x):\n",
    "    return np.sin(2 * np.pi * x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_train, y_train = create_toy_data(f, 10)\n",
    "x_test , y_test  = create_toy_data(f, 100)\n",
    "x_exact, y_exact = create_toy_data(f, 100, noise=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.scatter(x_train, y_train, facecolor='none', edgecolors='b', s=50, label='training data')\n",
    "plt.plot(x_exact, y_exact, c='g', label='$\\sin(2\\pi x)$')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Regression 回归"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Regression(object):\n",
    "    \"\"\"Base class for regression 基本类\n",
    "    \"\"\"\n",
    "    pass   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Linear Regression 线性回归"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "class LinearRegression(Regression):\n",
    "    \"\"\"Linear Regression Model 线性回归模型\n",
    "    y = X @ w\n",
    "    \"\"\"        \n",
    "    def fit(self, X, y):\n",
    "        \"\"\"performe least square fitting\n",
    "        \n",
    "        Params\n",
    "        ======\n",
    "        X: (N, D) np.ndarray: from x = np.array()\n",
    "            Polynomial feature 多项式特征\n",
    "        y: (N,) np.ndarray\n",
    "            Target\n",
    "        \"\"\"\n",
    "        # np.linalg.pinv(X):inv of X\n",
    "        self.w = np.linalg.pinv(X) @ y\n",
    "    \n",
    "    def predict(self, X):\n",
    "        \"\"\"make prediction given input\n",
    "        \n",
    "        Params\n",
    "        ======\n",
    "        X: (N, D) np.ndarray\n",
    "        \n",
    "        Returns\n",
    "        =======\n",
    "        y: (N,) np.ndarray\n",
    "            prediction of each sample\n",
    "        \"\"\"\n",
    "        y = X @ self.w\n",
    "        return y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Polynomial Feature"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "import itertools\n",
    "import functools\n",
    "\n",
    "class PolynormialFeature(object):\n",
    "    \"\"\"Polynomial features\n",
    "    transforms input array with polynomial feature\n",
    "    \n",
    "    Examples\n",
    "    ========\n",
    "    Example 1\n",
    "    ---------\n",
    "    x = np.array([a, b])\n",
    "    y = PolynormialFeature(degree=2).transform(x)\n",
    "    y = [[1, a, a^2, a^3]\n",
    "         [1, b, b^2, b^3]]\n",
    "    \n",
    "    Example 2\n",
    "    ---------\n",
    "    x = np.array([[a, b], \n",
    "                  [c, d]])     \n",
    "    y = PolynormialFeature(degree=2).transform(x)\n",
    "    y = [[1, a, b, a^2, a*b, b^2],\n",
    "         [1, c, d, c^2, c*d, d^2]]    \n",
    "    \"\"\"\n",
    "    def __init__(self, degree=2):\n",
    "        \"\"\"construct polynomial features\n",
    "        \n",
    "        Params\n",
    "        ======\n",
    "        degree: int\n",
    "            degree of polynomials\n",
    "        \"\"\"\n",
    "        if not isinstance(degree, int):\n",
    "            raise TypeError(\"degree should be int\")\n",
    "        self.degree = degree\n",
    "        \n",
    "    def transform(self, x):\n",
    "        \"\"\"transforms input array with polynomial features\n",
    "        \n",
    "        Params\n",
    "        ======\n",
    "        x: (sample_size, n) np.ndarray\n",
    "            input array\n",
    "            \n",
    "        Returns\n",
    "        =======\n",
    "        output: (sample_size, C_{n+d}^d)\n",
    "        \"\"\"\n",
    "        if x.ndim == 1: # x:[1 2]\n",
    "            x = x[:, None] # ndim += 1 x:[[1]\\n[2]]\n",
    "        x_t = x.transpose() # 转置 x = [[1 2]]\n",
    "        features = [np.ones(len(x))] #features:[array([1., 1.])]\n",
    "        for d in range(1, self.degree + 1):\n",
    "            for item in itertools.combinations_with_replacement(x_t, d):\n",
    "                # itertools.combinations_with_replacement('ABC',2) --> AA AB AC BB BC CC\n",
    "                features.append(functools.reduce(lambda x, y: x * y, item))\n",
    "                # functools.reduce(lambda x, y: x+y, [1,2,3,4,5]) calculates ((((1+2)+3)+4)+5)\n",
    "        return np.asarray(features).transpose() \n",
    "        # np.assarray():convert a list into an array. eg: a:[1,2] --> np.asarray(a):array([1,2])              "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1. 1.]\n",
      " [1. 2. 4.]]\n"
     ]
    }
   ],
   "source": [
    "x = np.array([1, 2])\n",
    "feature = PolynormialFeature(2).transform(x)\n",
    "print(feature)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1. 2. 1. 2. 4.]\n",
      " [1. 2. 3. 4. 6. 9.]]\n"
     ]
    }
   ],
   "source": [
    "x = np.array([[1, 2],[2, 3]])\n",
    "feature = PolynormialFeature(2).transform(x)\n",
    "print(feature)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Curve Fitting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "feature = PolynormialFeature(9)\n",
    "X_train = feature.transform(x_train)\n",
    "X_test  = feature.transform(x_test)\n",
    "model = LinearRegression()\n",
    "model.fit(X_train, y_train)\n",
    "y = model.predict(X_test)\n",
    "    \n",
    "plt.scatter(x_train, y_train, facecolor='none', edgecolor='b', s=20, label='training_data')\n",
    "plt.plot(x_exact, y_exact, c='g', label='$\\sin(2\\pi x)$')\n",
    "plt.plot(x_test , y      , c='r', label='fitting')\n",
    "plt.ylim(-2, 2)\n",
    "plt.legend(bbox_to_anchor=(1.05,0.64), loc=2)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-0.06267972]\n",
      "[ 0.82208595 -1.76953135]\n",
      "[-1.01775398e-02  9.17294362e+00 -3.89548064e-01 -1.44038519e+02\n",
      "  3.46832672e+02 -3.17379365e+02  1.05352798e+02]\n",
      "[-1.74589201e-02  1.70475898e+02 -3.58658216e+03  3.07396780e+04\n",
      " -1.37937775e+05  3.58508525e+05 -5.60000280e+05  5.18841679e+05\n",
      " -2.62799120e+05  5.60629516e+04]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "for i, degree in enumerate([0, 1, 6, 9]):\n",
    "    plt.subplot(2, 2, i+1)\n",
    "    \n",
    "    feature = PolynormialFeature(degree)\n",
    "    X_train = feature.transform(x_train)\n",
    "    X_test  = feature.transform(x_test)\n",
    "\n",
    "    model = LinearRegression()\n",
    "    model.fit(X_train, y_train)\n",
    "    y = model.predict(X_test)\n",
    "    print(model.w)\n",
    "    \n",
    "    plt.scatter(x_train, y_train, facecolor='none', edgecolor='b', s=20, label='training_data')\n",
    "    plt.plot(x_exact, y_exact, c='g', label='$\\sin(2\\pi x)$')\n",
    "    plt.plot(x_test , y      , c='r', label='fitting')\n",
    "    plt.ylim(-2, 2)\n",
    "plt.legend(bbox_to_anchor=(1.05,0.64), loc=2)# legend位置\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Training and testing error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "def rmse(a, b):\n",
    "    \"\"\"Rooted Mean Squared Error\n",
    "    \n",
    "    Params:\n",
    "    ======\n",
    "    a: (n,) np.ndarray\n",
    "    b: (n,) np.ndarray\n",
    "    \"\"\"\n",
    "    return np.sqrt(np.mean(np.square(a - b)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYIAAAEHCAYAAACjh0HiAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3de3xU1bXA8d9KeITwrmJFAwkqyvtlRBQqWER5eMFKeUPFIggKKggVpWLFq/hCBUU0KqAQRQUrtKJwseIDUYmKVkAgQoCIrQEBg4AQsu4fOwkhTMKEzMmZZNb385kPOWfOzCyGMGvO2XuvJaqKMcaYyBXldwDGGGP8ZYnAGGMinCUCY4yJcJYIjDEmwlkiMMaYCGeJwBhjIlwFL59cRLoC04Fo4HlVfbDA/fWBF4FaOcdMVNWlRT3n6aefrgkJCd4EbIwx5dTnn3++S1XrBLrPs0QgItHATKALkA6sEZElqro+32F/BV5T1Vki0gRYCiQU9bwJCQmkpKR4FLUxxpRPIrKtsPu8vDTUFkhV1S2qehhYAPQqcIwCNXJ+rgns9DAeY4wxAXh5aehsYEe+7XTg4gLH/A1YLiJjgKrAFR7GY4wxJgAvzwgkwL6C9SwGAHNVNQ7oDswTkRNiEpERIpIiIikZGRkehGqMMZHLyzOCdKBevu04Trz0MwzoCqCqq0UkBjgd+DH/QaqaBCQBJCYmWnEkY0rZkSNHSE9P59ChQ36HYk4iJiaGuLg4KlasGPRjvEwEa4CGItIA+B7oDwwscMx2oDMwV0QaAzGAfeU3Jsykp6dTvXp1EhISEAl0sm/Cgaqye/du0tPTadCgQdCP8+zSkKpmAaOBZcAG3OygdSIyRUR65hx2OzBcRL4CXgGGqhflUJOTISEBoqLcn8nJIX8JY8qzQ4cOcdppp1kSCHMiwmmnnVbsMzdP1xHkrAlYWmDf5Hw/rwfaexkDyckwYgQcOOC2t21z2wCDBnn60saUJ5YEyoZT+Xcq/yuLJ006lgRyHTjg9htjjImARLB9e/H2G2PCzt69e3n66adP6bHdu3dn7969RR4zefJkVqxYcUrPXx6U/0RQv37x9htjSizUw3JFJYKjR48W+dilS5dSq1atIo+ZMmUKV1xResuYCsaclZUV1OOCPa64yn8iuP9+iI09fl+FCm6/MSbkcofltm0D1WPDciVJBhMnTuS7776jVatWTJgwgZUrV3L55ZczcOBAmjdvDsA111zDhRdeSNOmTUlKSsp7bEJCArt27SItLY3GjRszfPhwmjZtypVXXsnBgwcBGDp0KAsXLsw7/p577qFNmzY0b96cb7/9FoCMjAy6dOlCmzZtuPHGG4mPj2fXrl0nxLp8+XIuueQS2rRpQ58+fdi/f3/e806ZMoUOHTrw+uuv06lTJ+666y46duzI9OnT2bZtG507d6ZFixZ07tyZ7TlXLYYOHcq4ceO4/PLLueOOO3j//fdp1aoVrVq1onXr1mRmZp76G5tLVcvU7cILL9Rimz9fNT5eVUS1WjVVUE1JKf7zGBOh1q9fn/fzrbeqduxY+K1yZfdfrOCtcuXCH3PrrUW//tatW7Vp06Z52++9957Gxsbqli1b8vbt3r1bVVUPHDigTZs21V27dqmqanx8vGZkZOjWrVs1Ojpav/zyS1VV7dOnj86bN09VVa+77jp9/fXX846fMWOGqqrOnDlThw0bpqqqN998sz7wwAOqqvr2228roBkZGcfFmZGRob/73e90//79qqr64IMP6r333pv3vA899FDesR07dtRRo0blbV999dU6d+5cVVV94YUXtFevXnmx9ejRQ7OysvKO++ijj1RVNTMzU48cOXLC+5X/3ysXkKKFfK6W/zMCcLOD0tIgOxvS0+HMM2HkSDjJKaUxpvh+/bV4+09V27Ztj5srP2PGDFq2bEm7du3YsWMHmzdvPuExDRo0oFWrVgBceOGFpKWlBXzua6+99oRjPvroI/r37w9A165dqV279gmP++STT1i/fj3t27enVatWvPjii2zbdqzWW79+/Y47Pv/26tWrGTjQLbUaMmQIH330Ud59ffr0ITo6GoD27dszbtw4ZsyYwd69e6lQoeSTPz2dPhqWataEJ56A/v1h1iwYPdrviIwpU554ouj7ExLc5aCC4uNh5crQxVG1atW8n1euXMmKFStYvXo1sbGxdOrUKeBc+sqVK+f9HB0dnXdpqLDjoqOj867LaxBLnFSVLl268Morr5w05kDb+eWfBpr/uIkTJ9KjRw+WLl1Ku3btWLFiBY0aNTppbEWJjDOCgvr2hSuvhLvugp1W8NSYUAo0LBcbW7JhuerVqxd5LXzfvn3Url2b2NhYvv32Wz755JNTf7FCdOjQ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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "errors_train = []\n",
    "errors_test  = []\n",
    "\n",
    "for i in range(10):\n",
    "    feature = PolynormialFeature(i)\n",
    "    X_train = feature.transform(x_train)\n",
    "    X_test  = feature.transform(x_test)\n",
    "    \n",
    "    model = LinearRegression()\n",
    "    model.fit(X_train, y_train)\n",
    "    \n",
    "    y = model.predict(X_test)\n",
    "    errors_train.append(rmse(model.predict(X_train), y_train))\n",
    "    errors_test.append (rmse(model.predict(X_test ), y_test ))\n",
    "    \n",
    "plt.plot(errors_train, 'o-', c='b', label='training errors')\n",
    "plt.plot(errors_test , 'o-', c='r', label='testing errors')\n",
    "plt.xlabel('k')\n",
    "plt.ylabel('error')\n",
    "plt.legend()\n",
    "\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ridge Regression - Regularization\n",
    "岭回归 - 正则化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "class RidgeRegression(Regression):\n",
    "    \"\"\"Ridge regression\n",
    "    w^* = argmin \\|t - X @ w\\|^2 + alpha * \\|w\\|^2\n",
    "    \"\"\"\n",
    "    def __init__(self, alpha=1.):\n",
    "        self.alpha = alpha\n",
    "        \n",
    "    def fit(self, X, y):\n",
    "        \"\"\"MAP estimation of parameter\n",
    "        \n",
    "        Params\n",
    "        ======\n",
    "        X: (N, D) np.ndarray\n",
    "            Polynomial features\n",
    "        y: (N,) np.ndarray\n",
    "            Target\n",
    "        \"\"\"\n",
    "        eye = np.eye(X.shape[1])\n",
    "        self.w = np.linalg.solve(self.alpha * eye + X.T @ X, X.T @ y)  \n",
    "        # np.linalg.solve(A,b)\n",
    "        \n",
    "    def predict(self, X):\n",
    "        \"\"\"make prediction given input\n",
    "        \n",
    "        Params\n",
    "        ======\n",
    "        X: (N, D) np.ndarray\n",
    "            samples to predict their output\n",
    "        \n",
    "        Returns\n",
    "        =======\n",
    "        y: (N,) np.ndarray\n",
    "            prediction of each sample\n",
    "        \"\"\"\n",
    "        y = X @ self.w\n",
    "        return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[  0.34994297   5.5196171  -11.74451669  -3.65220262   2.7174529\n",
      "   5.094607     4.5985461    2.40804253  -0.66777277  -4.12987293]\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "feature = PolynormialFeature(9)\n",
    "X_train = feature.transform(x_train)\n",
    "X_test  = feature.transform(x_test)\n",
    "\n",
    "model = RidgeRegression(alpha=1e-3)\n",
    "model.fit(X_train, y_train)\n",
    "y = model.predict(X_test)\n",
    "print(model.w)\n",
    "\n",
    "plt.scatter(x_train, y_train, fc='none', ec='b', s=20, label='training data')\n",
    "plt.plot(x_exact, y_exact, c='g', label='$\\sin(2\\pi x)$')\n",
    "plt.plot(x_test , y, c='r', label='fitting')\n",
    "plt.ylim(-2, 2)\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
